/**
 * @file src/Motif.cpp
 *
 * @date 28-aug-2013
 *
 * @author Youri Hoogstrate
 *
 * @section LICENSE
 * yh-kt-fold can predict RNA 2D structures including K-turns.
 * Copyright (C) 2012-2013 Youri Hoogstrate
 *
 * This file is part of yh-kt-fold.
 *
 * yh-kt-fold is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * yh-kt-fold is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */



#include "Motif.h"



/**
 * @brief
 *
 * @date 28-aug-2013
 */
Motif::Motif(std::string &arg_motif5p, std::string &arg_motif3p, std::string &arg_name, std::string &arg_bonds, float &arg_gibbs_free_energy, bool arg_is_reversed)
{
	this->set_bonds_and_motifs(arg_motif5p, arg_motif3p, arg_bonds);
	this->name = arg_name;
	
	this->gibbs_free_energy = arg_gibbs_free_energy;
	this->is_reversed = arg_is_reversed;
	
	this->traceback_position = 0;
	
	
	// Debug:
	//this->print_signature();
}


void Motif::print_signature(void)
{

	// Print signature
	printf("   n: %s", this->name.c_str());
	if(this->is_reversed)
	{
		printf(" (reverse*)");
	}
	printf("\n  5': [%s]\n  3': [%s]\n   e: %f\n", this->motif5p.c_str(), this->motif3p.c_str(), this->gibbs_free_energy);
	
	//print bonds
	for(unsigned int k = 0; k < this->bonds.size(); k++)
	{
		std::cout << this->bonds[k][0] << "," << this->bonds[k][1] << "\n";
	}
	printf("\n\n");
	
}



/**
 * @brief
 *
 * @section DESCRIPTION
 * Example:
 *
 * 5') xACUUG...
 *      | | |   )
 * 3') xA U G...
 *
 * for bond k:
 * [0]: -1,1
 * [1]: -3,2
 * [2]: -5,3
 * [x]: -6,4
 *
 * @date 04-sept-2013
 */
void Motif::set_bonds_and_motifs(std::string &arg_motif5p, std::string &arg_motif3p, std::string &arg_bonds)
{
	this->bonds.clear();
	
	int i = -1;
	int j = 1;
	char bond;
	unsigned int n = arg_bonds.size();
	
	this->motif5p = "";
	this->motif3p = "";
	
	
	for(int k = n - 1; k >= 0; --k)
	{
		bond = arg_bonds[k];
		
		// Add motif
		if(bond != ' ')
		{
			this->bonds.push_back( {{i, j}});
		}
		
		
		if(arg_motif5p[k] != ' ')
		{
			this->motif5p = arg_motif5p[k] + this->motif5p;
			i--;
		}
		if(arg_motif3p[k] != ' ')
		{
			this->motif3p += arg_motif3p[k];
			j++;
		}
	}
	/*
	for(int k = 0; k < n; k++)
	{
		if(bond != ' ')
		{
			this->bonds.push_back( {{i, j}});
		}
		
		
		if(arg_motif5p[k] != ' ')
		{
			this->motif5p += arg_motif5p[k];
			i++;
		}
		if(arg_motif3p[k] != ' ')
		{
			this->motif3p += arg_motif3p[k];
			j++;
		}
	}*/
	
	this->bonds.push_back( {{i, j}});
}



/**
 * @brief Returns the length of the motifs.
 *
 * @date 25-jul-2013
 */
unsigned int Motif::get_length(int arg_prime)
{
	int length = 0;
	
	switch(arg_prime)
	{
		case FIVE_PRIME:
			length = this->motif5p.size();
			break;
		case THREE_PRIME:
			length = this->motif3p.size();
			break;
		default:
			fprintf(stderr, "Fatal error: wrong argument\n");
			exit(1);
			break;
	}
	
	return length;
}



/**
 * @brief Finds the next offset for the traceback algorithm
 *
 * @param arg_i The offset of i
 * @param arg_j The offset of j
 *
 * @date 28-aug-2013
 */
bool Motif::traceback_pop(int *arg_i, int *arg_j)
{
	bool is_not_last_iteration = true;
	
	if(this->traceback_position < this->bonds.size())
	{
		(*arg_i) = (int) this->bonds[this->traceback_position][0];
		(*arg_j) = (int) this->bonds[this->traceback_position][1];
		
		if(this->traceback_position < (this->bonds.size() - 1))
		{
			this->traceback_position++;
		}
		else
		{
			this->traceback_position = 0;
			is_not_last_iteration = false;
		}
	}
	else
	{
		fprintf(stderr, "fatal error: Invalid traceback.");
		exit(1);
	}
	
	
	
	return is_not_last_iteration;
}
